/*
							Copyright (C) 2010  Alourien Team
									
						This file is part of the Alourien Engine.

    The Alourien Engine is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    The Alourien Engine is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with the Alourien Engine.  If not, see <http://www.gnu.org/licenses/>.
	
 *File Name: WinMain.cpp
 *Programmer Name: Manuel Cuellar
 *Date of last update: 10/01/2010
 *
 *Purpose: To create the main window, and to initialize the engine
 * which will then run the game.
 *
 *Basic info: Done using Win32 API programming. This code also handles
 * important game events, such as preload, initialization, the update
 * process, and the all important game end
 *
 *UPDATES:
 *
 *
 *
 *
 */

#include <sstream>
#include "WinMain.h"
#include "Alourien.h"

//Macro to read the key states
#define KEY_DOWN(vk) ((GetASyncKeyState(vk) & 0x8000)?1:0)

//Global handle variables
HINSTANCE g_hInst;
HWND g_hWnd;
int g_nCmdShow;

//Declare global engine object
Alourien::Engine *g_engine;

bool gameover;

//Window event callback function
LRESULT CALLBACK WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch(msg)
	{
	case WM_QUIT:
	case WM_CLOSE:
	case WM_DESTROY:
		gameover = true;
		break;
	}

	return DefWindowProc(hWnd, msg, wParam, lParam);
}

//Entry point to the main Window
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine,	\
						int nCmdShow)
{
	MSG msg;
	srand((unsigned int)time(NULL));
	g_hInst = hInst;
	g_nCmdShow = nCmdShow;
	DWORD dwStyle, dwExStyle;
	RECT windowRect;

	//CREATE OUR ENGINE OBJECT
	g_engine = new Alourien::Engine();

	//Check for preload errors. Displays message box is load fails, then exits program as failed
	if(!game_preload())
	{
		MessageBox(g_hWnd, "Error in game preload", "Error", MB_OK);
		return 0;
	}

	//Get window caption string from engine
	char title[255];
	sprintf_s(title, "%s", g_engine->getAppTitle().c_str());

	//Set window dimensions
	windowRect.left = (long)0;
	windowRect.right = (long)g_engine->getScreenWidth();
	windowRect.top = (long)0;
	windowRect.bottom = (long)g_engine->getScreenHeight();

	//Create the window class structure
	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);

	//Fill the struct with necessary info
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = (WNDPROC)WinProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInst;
	wcex.hIcon = NULL;
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = NULL;
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = title;
	wcex.hIconSm = NULL;

	//Set up the window
	RegisterClassEx(&wcex);

	//Set up the screen in either windows or fullscreen
	if(g_engine->getFullScreen())
	{
		DEVMODE dm;
		memset(&dm, 0, sizeof(dm));
		dm.dmSize = sizeof(dm);
		dm.dmPelsWidth = g_engine->getScreenWidth();
		dm.dmPelsHeight = g_engine->getScreenHeight();
		dm.dmBitsPerPel = g_engine->getColorDepth();
		dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

		if(ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
		{
			MessageBox(NULL, "Display mode failed", NULL, MB_OK);
			g_engine->setFullScreen(false);
		}

		dwStyle = WS_POPUP;
		dwExStyle = WS_EX_APPWINDOW;
		ShowCursor(FALSE);
	}
	else
	{
		dwStyle = WS_OVERLAPPEDWINDOW;
		dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
	}

	//Adjust window to the requested size
	AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);

	//Create the program window
	g_hWnd = CreateWindowEx(0,
		title, //Window Class
		title, //title bar
		dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
		0, 0, //x,y coordinates
		windowRect.right - windowRect.left, //width of the window
		windowRect.bottom - windowRect.top, //height of the window
		0,
		0,
		g_hInst, //application instance
		0);

	//Check for window creation errors
	if(!g_hWnd)
	{
		MessageBox(g_hWnd, "Error creating program window", "Error", MB_OK);
		return 0;
	}

	//Display the window
	ShowWindow(g_hWnd, g_nCmdShow);
	UpdateWindow(g_hWnd);

	//Initialize the engine
	g_engine->setWindowHandle(g_hWnd);
	if(!g_engine->Init(g_engine->getScreenWidth(), g_engine->getScreenHeight(),
		g_engine->getColorDepth(), g_engine->getFullScreen()))
	{
		MessageBox(g_hWnd, "Error initializing the engine", "Error", MB_OK);
		return 0;
	}

	//Main message loop
	gameover = false;
	while(!gameover)
	{
		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		g_engine->Update();
	}

	if(g_engine->getFullScreen())
	{
		ShowCursor(TRUE);
	}

	g_engine->Close();
	delete g_engine;

	return 1;
}